﻿using DocumentFormat.OpenXml.Bibliography;
using DocumentFormat.OpenXml.Office2010.Excel;
using DocumentFormat.OpenXml.Spreadsheet;
using Hangfire.Server;
using housingsafety.server.Caching.Core;
using housingsafety.server.Entities;
using housingsafety.server.Entities.DataModels;
using housingsafety.server.Helpers;
using housingsafety.server.Models;
using housingsafety.server.Repository;
using housingsafety.server.Security;
using housingsafety.server.Snowflake;
using housingsafety.server.Svcs;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace housingsafety.server.Controllers
{
    /// <summary>
    /// 身份验证(OK)
    /// </summary>
    public class AuthenticationController : BaseController<AuthenticationController>
    {
        private readonly ISmsHelper _smsHelper;
        private readonly IAuthenticateService _authService;
        private readonly IRepository<ZmUser> _userRepository;
        private readonly ICache _cache;
        private readonly ZmDbContext _dbContext;
        private readonly IRepository<ZmDepartment> _departmentRepository;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="authService">授权接口</param>
        /// <param name="smsHelper">短信验证接口</param>
        /// <param name="userRepository">用户存储</param>
        /// <param name="cacheProvider"></param>
        /// <param name="logger">日志接口</param>
        /// <param name="systemLogRepository"></param>
        public AuthenticationController(IAuthenticateService authService
            , IRepository<ZmDepartment> departmentRepository
            , IRepository<ZmUser> userRepository
            , ZmDbContext dbContext
            , ICacheProvider cacheProvider
            , ISmsHelper smsHelper
            , ILogger<AuthenticationController> logger
            , IRepository<ZmSystemLog> systemLogRepository)
            : base(logger, systemLogRepository)
        {
            _departmentRepository = departmentRepository;
            _dbContext = dbContext;
            _cache = cacheProvider.CreateCache();
            _userRepository = userRepository;
            _authService = authService;
            _smsHelper = smsHelper;
        }

        ///// <summary>
        ///// 登录
        ///// </summary>
        ///// <param name="request">请求参数</param>
        ///// <returns>请求token</returns>
        //[AllowAnonymous]
        //[HttpPost("login/in")]
        //[Produces("application/json")]
        //[ProducesResponseType(typeof(RespRet<AuthenticateResponse>), 200)]
        //public RespRet<AuthenticateResponse> Login([FromBody] AuthenticateRequest request)
        //{

        //    if (!ModelState.IsValid)
        //    {
        //        return new RespRet<AuthenticateResponse>(false, "Invalid Request");
        //    }

        //    if (string.IsNullOrWhiteSpace(request.Id))
        //    {
        //        return new RespRet<AuthenticateResponse>(false, "请登录");
        //    }
        //    var user = _userRepository.FirstOrDefault(c => c.Qaakey == request.Id && c.IsDelete != 1);
        //    if (user == null)
        //    {
        //        if (string.IsNullOrWhiteSpace(request.UserName) && string.IsNullOrWhiteSpace(request.Pwd))
        //        {
        //            return new RespRet<AuthenticateResponse>(false, "请登录");
        //        }
        //        var response1 = _authService.Authenticate(request, this.IpAddress());
        //        if (response1.Succ)
        //        {
        //            this.SetTokenCookie(response1.Data.RefreshToken);
        //        }
        //        return response1;
        //    }
        //    var response = _authService.AuthenticateId(user, this.IpAddress());
        //    if (response == null)
        //    {
        //        return new RespRet<AuthenticateResponse>(false, "用户不存在");
        //    }

        //    if (response.Succ)
        //    {
        //        this.SetTokenCookie(response.Data.RefreshToken);
        //    }
        //    return response;
        //}



        ///// <summary>
        ///// 绑定id
        ///// </summary>
        ///// <param name="request">请求参数</param>
        ///// <returns>请求token</returns>
        //[AllowAnonymous]
        //[HttpPost("login/confirm")]
        //[Produces("application/json")]
        //[ProducesResponseType(typeof(RespRet<int>), 200)]
        //public RespRet<int> Confirm([FromQuery] string id)
        //{
        //    try
        //    {
        //        if (string.IsNullOrEmpty(id))
        //        {
        //            return new RespRet<int>(false, "ID不能为空");
        //        }
        //        var userNumber = this.CurrentUser();
        //        if (string.IsNullOrWhiteSpace(userNumber))
        //        {
        //            return new RespRet<int>(false, "请登录后再绑定");
        //        }
        //        if (!ModelState.IsValid)
        //        {
        //            return new RespRet<int>(false, "Invalid Request");
        //        }

        //        var user = _dbContext.ZmUser.AsNoTracking().FirstOrDefault(c => c.Number == userNumber && c.IsDelete != 1);
        //        if (user == null)
        //        {
        //            var res = new RespRet<int>(false, "绑定失败");
        //            WriteSystemLog("login/confirm", res, id);
        //            return res;
        //        }
        //        if (user.Qaakey == id)
        //        {
        //            var res = new RespRet<int>(false, "已绑定，无需再次操作");
        //            WriteSystemLog("login/confirm", res, id);
        //            return res;
        //        }
        //        if (user.Qaakey !=null)
        //        {
        //            var res = new RespRet<int>(false, "该账号已和他人绑定，请核对账号");
        //            WriteSystemLog("login/confirm", res, id);
        //            return res;
        //        }

        //        user.Qaakey = id;
        //        _dbContext.Update(user);
        //        if (_dbContext.SaveChanges() > 0)
        //        {
        //            var res = new RespRet<int>(true, "绑定成功");
        //            WriteSystemLog("login/confirm", res, id);
        //            return res;
        //        }
        //        else
        //        {
        //            var res = new RespRet<int>(false, "绑定失败");
        //            WriteSystemLog("login/confirm", res, id);
        //            return res;
        //        }
        //    }
        //    catch (Exception ex)
        //    {

        //        var res = new RespRet<int>(false, ex.ToString());
        //        WriteSystemLogError("login/confirm", res, id);
        //        res.Msg = "绑定失败";
        //        return res;
        //    }
        //}


        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="request">请求参数</param>
        /// <returns>请求token</returns>
        [AllowAnonymous]
        [HttpPost("login/in")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet<AuthenticateResponse>), 200)]
        public RespRet<AuthenticateResponse> Login([FromBody] AuthenticateRequest request)
        {


            if (!ModelState.IsValid)
            {
                return new RespRet<AuthenticateResponse>(false, "Invalid Request");
            }

            if (string.IsNullOrWhiteSpace(request.Id))
            {
                return new RespRet<AuthenticateResponse>(false, "请登录");
            }
            var user = _userRepository.FirstOrDefault(c => c.Qaakey == request.Id && c.IsDelete != 1&&c.Disabled!=1&&c.IsSecondaryAccount==null);
            if (user == null)
            {

                if (string.IsNullOrWhiteSpace(request.UserName) && string.IsNullOrWhiteSpace(request.Pwd))
                {
                    return new RespRet<AuthenticateResponse>(false, "请登录");
                }
                var response1 = _authService.Authenticate(request, this.IpAddress());
                if (response1.Succ)
                {
                    this.SetTokenCookie(response1.Data.RefreshToken);
                }
                WriteSystemLog("login/in", response1, request);
                return response1;
            }
            var response = _authService.AuthenticateId(user, this.IpAddress());
            if (response == null)
            {
                return new RespRet<AuthenticateResponse>(false, "用户不存在");
            }
            if (response.Succ)
            {
                this.SetTokenCookie(response.Data.RefreshToken);
            }
            WriteSystemLog("login/in", response, request);
            return response;
        }



        /// <summary>
        /// 切换市级账号
        /// </summary>
        /// <param name="request">请求参数</param>
        /// <returns>请求token</returns>
        [HttpPost("login/switch-user")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet<AuthenticateResponse>), 200)]
        public RespRet<AuthenticateResponse> Switch([FromBody] AuthenticateRequest request)
        {

            if (!ModelState.IsValid)
            {
                return new RespRet<AuthenticateResponse>(false, "Invalid Request");
            }


            if (string.IsNullOrWhiteSpace(request.Id))
            {
                return new RespRet<AuthenticateResponse>(false, "请登录");
            }
            var userNumber = this.CurrentUser();
            var last_user = _dbContext.ZmUser.FirstOrDefault(u => u.Number == userNumber && u.IsDelete != 1 && u.Disabled != 1);
            if (last_user == null)
            {
                return new RespRet<AuthenticateResponse>(false, "没有权限切换");
            }
            ZmUser user = null;
            if (last_user.RoleType == 3)
            {
                user = _userRepository.FirstOrDefault(c => c.Qaakey == request.Id && c.IsDelete != 1 && c.Disabled != 1 && c.RoleType==2);
            }
            if (last_user.RoleType == 2)
            {
                user = _userRepository.FirstOrDefault(c => c.Qaakey == request.Id && c.IsDelete != 1 && c.Disabled != 1 && c.RoleType ==3);
                if (user == null)
                {
                    return new RespRet<AuthenticateResponse>(false, "没有可切换的账号");
                }
            }
            if (user == null)
            {
                var usercity = last_user;
                usercity.RoleType = 2;
                usercity.IsSecondaryAccount = 1;
                object dis = new { Id = "110000", RegionCode = "110000", RegionName = "北京市" };
                usercity.District = JsonConvert.SerializeObject(dis);
                var userNumberadd = new IdWorker(1, 1).NextId().ToString();
                usercity.Number = userNumberadd;
                usercity.Id=Guid.NewGuid().ToString("N");
                _userRepository.DbContext.Add(usercity);
                int res=_userRepository.DbContext.SaveChanges();
                if (res > 0)
                {
                    user = _userRepository.FirstOrDefault(c => c.Qaakey == request.Id && c.IsDelete != 1 && c.Disabled != 1 && c.RoleType == 2);
                }
                else
                {
                    return new RespRet<AuthenticateResponse>(false, "切换账号失败，请重试");
                }
            }
            var response = _authService.AuthenticateId(user, this.IpAddress());
            if (response == null)
            {
                return new RespRet<AuthenticateResponse>(false, "用户不存在");
            }
            if (response.Succ)
            {
                this.SetTokenCookie(response.Data.RefreshToken);
            }
            WriteSystemLog("login/switch-user", response, request);
            return response;
        }





        /// <summary>
        /// 绑定id
        /// </summary>
        /// <param name="request">请求参数</param>
        /// <returns>请求token</returns>
        [AllowAnonymous]
        [HttpPost("login/confirm")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet<int>), 200)]
        public RespRet<int> Confirm([FromQuery] string id, [FromQuery] string regioncode, [FromQuery] string name)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(id))
                {
                    return new RespRet<int>(false, "ID不能为空");
                }
                if (string.IsNullOrWhiteSpace(regioncode))
                {
                    return new RespRet<int>(false, "行政区划代码不能为空");
                }
                if(regioncode.Length == 4|| regioncode.Length == 3)
                {
                    regioncode = "110000";
                }
                if (regioncode.Length != 3 && regioncode.Length != 6)
                {
                    if (string.IsNullOrWhiteSpace(name))
                    {
                        return new RespRet<int>(false, "真实姓名不能为空");
                    }
                }

                var user = _dbContext.ZmUser.AsNoTracking().FirstOrDefault(c => c.Qaakey == id && c.IsDelete != 1&&c.Disabled!=1);
                if (user != null)
                {
                    var res = new RespRet<int>(false, "已绑定村庄，无需再次绑定");
                    WriteSystemLog("login/confirm", res,new { id= id,regioncode=regioncode,name =name} );
                    return res;
                }

                var departments = _cache.Get("departments") as List<ZmDepartment>;
                if (null == departments)
                {
                    departments = _departmentRepository.Query().ToList();
                    _cache.Set("departments", departments);
                }
                var region = departments.Where(c => c.RegionCode == regioncode && c.RegionalLevel == "7").FirstOrDefault();
                short roletype = 5;
                if (region == null)
                {
                    region = departments.Where(c => c.RegionCode == regioncode && c.RegionalLevel == "6").FirstOrDefault();
                    roletype = 4;
                    if (region == null)
                    {
                        region = departments.Where(c => c.RegionCode == regioncode && c.RegionalLevel == "5").FirstOrDefault();
                        roletype = 3;
                        if (region == null)
                        {
                            region = departments.Where(c => c.RegionCode == regioncode && c.RegionalLevel == "3").FirstOrDefault();
                            roletype = 2;
                        }
                    }
                    if (region == null)
                    {
                        var res = new RespRet<int>(false, "未找到行政区划，请核对行政区划代码");
                        WriteSystemLog("login/confirm", res, new { id = id, regioncode = regioncode, name = name });
                        return res;
                    }
                }
                var District = new { Id = region.RegionCode, RegionCode = region.RegionCode, RegionName = region.RegionName };
                var userNumber = new IdWorker(1, 1).NextId().ToString();

                var useradd = new ZmUser
                {
                    Id = Guid.NewGuid().ToString("N"),
                    CreateIp = this.IpAddress(),
                    CreateOn = DateTime.Now,
                    CreateBy = id,
                    Group = 1,
                    Uname = id,
                    RoleType = roletype,
                    Nickname = name,
                    Number = userNumber,
                    Salt = "1",
                    Qaakey = id,
                    District = JsonConvert.SerializeObject(District),
                    Disabled = 0
                };
                _dbContext.Add(useradd);
                if (_dbContext.SaveChanges() > 0)
                {
                    var res = new RespRet<int>(true, "绑定成功");
                    WriteSystemLog("login/confirm", res, new { id = id, regioncode = regioncode, name = name });
                    return res;
                }
                else
                {
                    var res = new RespRet<int>(false, "绑定失败");
                    WriteSystemLog("login/confirm", res, new { id = id, regioncode = regioncode, name = name });
                    return res;
                }
            }
            catch (Exception ex)
            {
                var res = new RespRet<int>(false, ex.ToString());
                WriteSystemLogError("login/confirm", res, new { id = id, regioncode = regioncode, name = name });
                res.Msg = "绑定失败";
                return res;
            }
        }





        /// <summary>
        /// 退出登录
        /// </summary>
        /// <returns></returns>
        [HttpPost("login/out")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet), 200)]
        public RespRet LoginOut()
        {
            // accept token from request body or cookie
            var token = this.CurrentUser() ?? Request.Cookies["refreshToken"];
            if (string.IsNullOrEmpty(token))
            {
                return new RespRet(false, "token is required");
            }

            var response = _authService.RevokeToken(token, this.IpAddress());
            if (!response.Succ)
            {
                return new RespRet(false, "token not found");
            }

            this.RemoveTokenCookie();
            return new RespRet(true, "token revoked");
        }

        /// <summary>
        /// 刷新Token
        /// </summary>
        /// <param name="model">刷新Token信息</param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("tokens/refresh")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet<AuthenticateResponse>), 200)]
        public RespRet<AuthenticateResponse> RefreshToken([FromQuery] RefreshTokenRequest model)
        {
            var refreshToken = model.Token ?? Request.Cookies["refreshToken"];
            if (string.IsNullOrEmpty(refreshToken))
            {
                return new RespRet<AuthenticateResponse>(false, "refreshToken is required");
            }

            var response = _authService.RefreshToken(refreshToken, this.IpAddress());
            if (response == null)
            {
                return new RespRet<AuthenticateResponse>(false, "Invalid token");
            }

            if (response.Succ)
            {
                this.SetTokenCookie(response.Data.RefreshToken);
            }

            return (response);
        }

        /// <summary>
        /// Token检查
        /// </summary>
        /// <returns></returns>
        [HttpGet("tokens/check")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet), 200)]
        [ProducesResponseType(401)]
        public RespRet CheckToken()
        {
            return new RespRet(true, "Pass");
        }



        /// <summary>
        /// 导入
        /// </summary>
        /// <returns></returns>
        [HttpPost("villages/dynamic/UploadFile")]
        public Object UploadFile([FromForm] IFormFile file)
        {
            var userNumber = this.CurrentUser();
            if (string.IsNullOrEmpty(userNumber))
            {
                return new RespRet<string>(false, "user not logined");
            }

            var user = _userRepository.FirstOrDefault(u => u.Number == userNumber && u.IsDelete != 1&&u.Disabled!=1);
            if (null == user)
            {
                return new RespRet<string>(false, "用户名不存在");
            }
            // 上传后的文件
            // var filePost = village;
            var filePost = file;
            // 文件名
            string fileName = filePost.FileName;
            var guid = Guid.NewGuid().ToString("N");
            // 服务器上文件要保存的路径
            var today = DateTime.Today.ToString().Replace("0:00:00", "").Replace("/", "-");
            string TruePath = Directory.GetCurrentDirectory() + "/wwwroot/files/" + today + "/" + guid + Path.GetExtension(fileName);
            if (!Directory.Exists(Directory.GetCurrentDirectory() + "/wwwroot/files/" + today))
            {
                Directory.CreateDirectory(Directory.GetCurrentDirectory() + "/wwwroot/files/" + today);
            }
            // 保存文件sy
            using (FileStream fs = System.IO.File.Create(TruePath.Replace(" ", "")))
            {
                filePost.CopyTo(fs);
            }
            Stream stream = filePost.OpenReadStream();
            XSSFWorkbook workbook = new XSSFWorkbook(stream);//创建工作薄，并读取文件流
            XSSFSheet sheet = (XSSFSheet)workbook.GetSheetAt(0);//获取第一个sheet
            var tmpCount = sheet.LastRowNum;
            List<ZmUser> userList = new List<ZmUser>();

            XSSFRow title = (XSSFRow)sheet.GetRow(0);
            if (title.Cells[0].RichStringCellValue.ToString().Replace(" ", "") != "姓名")
            {
                return new RespRet<string>(false, "第一列列名应为姓名");
            }
            if (title.Cells[1].RichStringCellValue.ToString().Replace(" ", "") != "村代码")
            {
                return new RespRet<string>(false, "第二列列名应为村代码");
            }
            if (title.Cells[2].RichStringCellValue.ToString().Replace(" ", "") != "企安安key")
            {
                return new RespRet<string>(false, "第三列列名应为企安安key");
            }
            for (int i = 1; i <= tmpCount; i++)
            {
                XSSFRow row = (XSSFRow)sheet.GetRow(i);//根据下标获取行数据


                if (row.GetCell(0) == null || string.IsNullOrEmpty(row.GetCell(0).ToString()))
                {
                    return new RespRet<string>(false, $"第一列第{i + 1}行不能为空");
                }
                if (row.GetCell(1) == null || string.IsNullOrEmpty(row.GetCell(1).ToString()))
                {
                    return new RespRet<string>(false, $"第二列第{i + 1}行不能为空");
                }
                if (row.GetCell(2) == null || string.IsNullOrEmpty(row.GetCell(2).ToString()))
                {
                    return new RespRet<string>(false, $"第三列第{i + 1}行不能为空");
                }

                //姓名
                var VillageOwnership = row.Cells[0].RichStringCellValue.ToString();
                if (string.IsNullOrWhiteSpace(VillageOwnership))
                {
                    return new RespRet<string>(false, $"第{i + 1}行编码格式不正确");
                }
                //村庄
                var VillageName = row.Cells[1].RichStringCellValue.ToString();
                if (string.IsNullOrWhiteSpace(VillageName))
                {
                    return new RespRet<string>(false, $"第{i + 1}行村代码不能为空");
                }
                //村庄
                var qaakey = row.Cells[2].RichStringCellValue.ToString();
                if (string.IsNullOrWhiteSpace(VillageName))
                {
                    return new RespRet<string>(false, $"第{i + 1}行村代码不能为空");
                }

                var ex = _dbContext.ZmUser.FirstOrDefault(c => c.Qaakey == qaakey);
                if (ex != null)
                {
                    return new RespRet<string>(false, $"企安安key{qaakey}已经导入，无需再次导入");
                }

                var departments = _cache.Get("departments") as List<ZmDepartment>;
                if (null == departments)
                {
                    departments = _departmentRepository.Query().ToList();
                    _cache.Set("departments", departments);
                }
                var region = departments.Where(c => c.RegionCode == VillageName && c.RegionalLevel == "7").FirstOrDefault();
                if (region == null)
                {
                    var res = new RespRet<int>(false, "未找到村庄，请核对村代码");
                    WriteSystemLog("login/confirm", res, VillageName);
                    return res;
                }
                var District = new { Id = region.RegionCode, RegionCode = region.RegionCode, RegionName = region.RegionName };
                var userNumberadd = new IdWorker(1, 1).NextId().ToString();
                var useradd = new ZmUser
                {
                    Id = Guid.NewGuid().ToString("N"),
                    CreateIp = this.IpAddress(),
                    CreateOn = DateTime.Now,
                    CreateBy = userNumber,
                    Group = 1,
                    Uname = qaakey,
                    RoleType = 5,
                    Number = userNumberadd,
                    Salt = "1",
                    Qaakey = qaakey,
                    Nickname = VillageOwnership,
                    District = JsonConvert.SerializeObject(District)
                };
                userList.Add(useradd);
            }
            _dbContext.AddRange(userList);
            var it = _dbContext.SaveChanges();
            stream.Dispose();
            workbook.Clear();
            // 返回文件在服务器上的路径
            return new RespRet<string>(true, "ok", "/files/" + guid + Path.GetExtension(fileName));

        }




    }
}
